package br.com.orion.sga.controller;

import java.util.List;
import org.apache.log4j.Logger;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;

import org.primefaces.context.RequestContext;

import br.com.orion.sga.exception.DaoException;
import br.com.orion.sga.model.entities.Responsavel;
import br.com.orion.sga.service.ResponsavelService;
import br.com.orion.sga.utils.MessageHandler;
import br.com.orion.sga.utils.validators.PessoaFisica;
import br.com.orion.sga.utils.validators.interfaces.Pessoa;

@ManagedBean(name="responsavelBean")
@ViewScoped
public class ResponsavelController {

	/**
	 * Services
	 */
	@ManagedProperty("#{responsavelService}")
	private ResponsavelService responsavelService;
	
	
	/**
	 * Attributes
	 */
	private List<Responsavel> responsibles;
	//List of responsible filtered
	private List<Responsavel> filteredResponsibles;
	
	/**
	 * Attributes of form to add a new responsible
	 */
	private String name;
	private String cpf;
	
	/**
	 * Attributes of form to edit a responsible
	 */
//	private Long idOfReponsible;
	
	/**
	 * Responsible Object to edit one register 
	 */
	private Responsavel responsibleEdit;
	
	/**
	 * Construct
	 */
	@PostConstruct
	public void init() {
		responsibles = responsavelService.listAll();
		
	}
	
	
	
	public void saveResponsible() {
		
		//check if the fields are filled correctly
		if (!fieldsFilled()) {
			MessageHandler.placeErrorMessage("Existem campos obrigatórios a serem preenchidos!");
			return;
		}
		
		boolean CPFIsValid = checkCPFIsValid();
		//check if form is Valid
		if (CPFIsValid) {
			
			//check if is an edit of responsible or not
			if (responsibleEdit != null) {
					
				responsibleEdit.setCpf(this.cpf);//set the attributes changed by user
				responsibleEdit.setNome(this.name);//set the attributes changed by user
				try {
					responsavelService.update(responsibleEdit);
					RequestContext context = RequestContext.getCurrentInstance();
					context.execute("PF('newResponsavelModal').hide();");
						
					//Clen the inputs
					cleanInputs();
					MessageHandler.placeInfoMessage("Responsável atualizado com sucesso!");
				} catch (DaoException e) {
					MessageHandler.placeErrorMessage(e.getMessage());
				}
					
			} else {//It is a new register of responsible
				
				//check if there is no a responsible registered on database with this same CPF
				if (!getExistingResponsibleByCPF(this.cpf)) {
					
					Responsavel resp = new Responsavel();
					resp.setNome(name);
					resp.setCpf(cpf);
					
					try {
						responsavelService.save(resp);
						RequestContext context = RequestContext.getCurrentInstance();
						context.execute("PF('newResponsavelModal').hide();");
						responsibles.add(resp);
						//Clen the inputs
						cleanInputs();
						MessageHandler.placeInfoMessage("Responsável salvo com sucesso!");
					} catch (DaoException e) {
						MessageHandler.placeErrorMessage(e.getMessage());
					} 
					
				} else {//there is a responsible with this CPF registered on database
					MessageHandler.placeErrorMessage("CPF já cadastrado!");
				}
			}
			
		} else {//form is invalid
			MessageHandler.placeErrorMessage("Informe um CPF Válido!");
		}
	}

	
	



	/**
	 * Validate the form
	 */
	private boolean checkCPFIsValid() {
		Pessoa pessoa = new PessoaFisica();
		boolean isValid = pessoa.validDocument(cpf);
		return isValid;
	}

	
	/**
	 * Method that will clean the all inputs on form
	 */
	public void cleanInputs() {
		this.cpf = null;
		this.name = null;
		responsibleEdit = null; //reset the object to edit the responsible
	}
	
	
	/**
	 * get existing Responsible by CPF
	 * @param cpf
	 * @return
	 */
	private boolean getExistingResponsibleByCPF(String cpf) {
		
		try {
			Responsavel resp = responsavelService.getByCPF(cpf);
			return true; //It was found a responsible with this same CPF on database
		} catch (DaoException e) {
			return false; //No found any responsible with this responsible
		}
	}

	
	/**
	 * check if fields are filled
	 * @return
	 */
	private boolean fieldsFilled() {
		if (this.cpf == null || this.cpf == "" || this.name == null || this.name == "")
			return false;
		
		return true;
	}
	
	/**
	 * Method that will be called when the user click on edit button
	 */
	public void clickOnEditResponsavel(Responsavel responsavel) {
		
		//Responsavel resp = responsavelService.getById(idOfResponsible);
		//this.idOfReponsible = responsavel.getId();
		name = responsavel.getNome();
		cpf = responsavel.getCpf();
		
		responsibleEdit = responsavel;
		
		RequestContext context = RequestContext.getCurrentInstance();
		context.execute("PF('newResponsavelModal').show();");
	}

	
	/**
	 * click on delete Responsible
	 * @param responsavel
	 */
	public void clickOnDeleteResponsavel(Responsavel responsavel) {
		//In order to avoid an detached instance exception it is necessary to get the object again in the same transaction to delete it
//		Responsavel resp = responsavelService.getById(responsavel.getId());
		try {
			responsavelService.delete(responsavel); //Remove the responsavel on database
			responsibles.remove(responsavel);//Remove the responsavel on data table
			MessageHandler.placeInfoMessage("Responsável removido com sucesso!");
		} catch (DaoException e) {
			MessageHandler.placeWarningMessage(e.getMessage());
		}
	}
	
	
	/**
	 *	Getters and Setters 
	 */
	public ResponsavelService getResponsavelService() {
		return responsavelService;
	}

	public void setResponsavelService(ResponsavelService responsavelService) {
		this.responsavelService = responsavelService;
	}

	public List<Responsavel> getResponsibles() {
		return responsibles;
	}

	public void setResponsibles(List<Responsavel> responsibles) {
		this.responsibles = responsibles;
	}

	public List<Responsavel> getFilteredResponsibles() {
		return filteredResponsibles;
	}

	public void setFilteredResponsibles(List<Responsavel> filteredResponsibles) {
		this.filteredResponsibles = filteredResponsibles;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getCpf() {
		return cpf;
	}
	
	public void setCpf(String cpf) {
		this.cpf = cpf;
	}
	
//	public Long getIdOfReponsible() {
//		return idOfReponsible;
//	}
//	
//	public void setIdOfReponsible(Long idOfReponsible) {
//		this.idOfReponsible = idOfReponsible;
//	}
}
